#include "App_LoRa_Proto.h"
#include "App_Mac.h"
#include "board.h"
#include "log.h"
#include "rtc-board.h"
#include "system.h"
#include "usart-board.h"

static uint16_t CRC16(const uint8_t* p_data, uint32_t len, uint16_t* p_crc)
{
    uint32_t i;
    uint16_t crc = 0xffff;
    if (NULL == p_data || NULL == p_crc || 0 == len) {
        return -1;
    }
    for (i = 0; i < len; i++) {
        crc = (unsigned char)(crc >> 8) | (crc << 8);
        crc ^= p_data[i];
        crc ^= (unsigned char)(crc & 0xff) >> 4;
        crc ^= (crc << 8) << 4;
        crc ^= ((crc & 0xff) << 4) << 1;
    }
    *p_crc = crc;
    return 0;
}

int Fill_LoraData_1B(uint8_t* appData, uint16_t* appDataSize, uint8_t data)
{
    appData[(*appDataSize)++] = data;
    return *appDataSize;
}

int Fill_LoraData_4B(uint8_t* appData, uint16_t* appDataSize, uint32_t data)
{
    appData[(*appDataSize)++] = (data & 0xFF000000) >> 24;
    appData[(*appDataSize)++] = (data & 0x00FF0000) >> 16;
    appData[(*appDataSize)++] = (data & 0x0000FF00) >> 8;
    appData[(*appDataSize)++] = (data & 0x000000FF);
    return *appDataSize;
}

int Fill_LoraData(uint8_t* appData, uint16_t* appDataSize, uint8_t cmd[], int len)
{
    int i = 0;
    for (i = 0; i < len; i++) {
        appData[(*appDataSize)++] = cmd[i];
    }
    return *appDataSize;
}

uint8_t appData[128];
uint16_t appSize = 0;
void App_Lora_Proto_SendData(uint8_t cmd[], int len)
{
    uint64_t time = 0;
    uint16_t crc = 0;
    int len_index = 0;

    if (len == 0) {
        return;
    }

    if (SystemLoRaData.loraTxMutex == NULL) {
        LOG_PRINTF(LL_DEBUG, "TxMutex is NULL\r\n");
        return;
    }
    xSemaphoreTake(SystemLoRaData.loraTxMutex, portMAX_DELAY);
    SystemLoRaData.systemState.flagBit.loraMutexState = 1;
    appSize = 0;
    /**
     * devType(2B)|time(8B)|dataType(1B)|length(1B)|data(NB)|CRC(2B)|
     *
     * */
    Fill_LoraData_1B(appData, &appSize, (SYSTEM_DEVICE_TYPE >> 8) & 0xFF);
    Fill_LoraData_1B(appData, &appSize, SYSTEM_DEVICE_TYPE & 0xFF);  // 设备类型

    time = RtcGetTimerValue();
    Fill_LoraData(appData, &appSize, (uint8_t*)&time, sizeof(time));

    Fill_LoraData_1B(appData, &appSize, REPORT_NORMAL_DATA_TYPE);  // 控制码

    len_index = appSize;
    Fill_LoraData_1B(appData, &appSize, (uint8_t)0);  // 数据长度

    Fill_LoraData(appData, &appSize, cmd, len);
    appData[len_index] = appSize - len_index - 1;

    CRC16((void*)appData, appSize, &crc);

    Fill_LoraData_1B(appData, &appSize, (crc >> 8) & 0xFF);
    Fill_LoraData_1B(appData, &appSize, crc & 0xFF);  // CRC检验值

    LOG_PRINTF(LL_DEBUG, "App_LoRa_Proto_SendNomalData:");
    for (uint8_t i = 0; i < appSize; i++) {
        LOG_PRINTF(LL_DEBUG, "%02x ", appData[i]);
    }
    LOG_PRINTF(LL_DEBUG, "\r\n");

    // uint8_t* allocData = (uint8_t*)pvPortMalloc(appSize);

    SendAppData(appData, appSize);
    OsMutexRelease(SystemLoRaData.loraTxMutex);
    SystemLoRaData.systemState.flagBit.loraMutexState = 0;
    // vPortFree(allocData);

    // DeviceState = DEVICE_STATE_SEND;  // 开始发送数据
}

void App_LoRa_Proto_SendAlarmData(uint8_t attrId, uint8_t alarm_type)
{
#if 0
    uint32_t time = 0;
    // uint8_t dataLen = 0;
    uint16_t crc = 0;

    memset((void*)SystemLoRaData.appData, 0, sizeof(SystemLoRaData.appData));
    SystemLoRaData.appDataSize = 0;
    // uint8_t *buffer = (void *)SystemLoRaData.appData;

    Fill_LoraData_1B((uint8_t)((SYSTEM_DEVICE_TYPE >> 8) & 0xFF));
    Fill_LoraData_1B((uint8_t)(SYSTEM_DEVICE_TYPE & 0xFF));  // 设备类型

    time = RtcGetTimerValue();
    Fill_LoraData_4B(time);

    if (alarm_type == 1) {
        Fill_LoraData_1B((uint8_t)REPORT_ALARM_RECOVERY_DATA_TYPE);  // 控制码
    } else {
        Fill_LoraData_1B((uint8_t)REPORT_ALARM_DATA_TYPE);  // 控制码
    }

#    if defined(CONFIG_DTU_485)
    Fill_LoraData_1B((uint8_t)21);

    for (uint8_t i = 0; i < SYSTEM_ATTRIBUTE_NUM; i++) {
        if (SystemParmData.attributeData[i].attrId == attrId) {
            Fill_LoraData_1B((uint8_t)SystemParmData.attributeData[i].attrId);  // 属性ID
            // Fill_LoraData_4B(SystemLoRaData.AttrSampleData[i].attrData); //属性值
            // Fill_LoraData_4B(SystemParmData.attributeData[i].attrAlarmMinData);  // 属性下限值
            //  Fill_LoraData_4B(SystemParmData.attributeData[i].attrAlarmRecoverMinData); // 属性恢复下限值
            // Fill_LoraData_4B(SystemParmData.attributeData[i].attrAlarmMaxData); //属性上限值
            // Fill_LoraData_4B(SystemParmData.attributeData[i].attrAlarmRecoverMaxData); // 属性恢复上限值
            break;
        }
    }
#    endif

#    if defined(CONFIG_DTU_AI)
    Fill_LoraData_1B((uint8_t)21);  // 数据长度

    for (uint8_t i = 0; i < SYSTEM_AI_ATTRIBUTE_NUM; i++) {
        if (SystemParmData.aiAttrData[i].attrId == attrId) {
            Fill_LoraData_1B((uint8_t)SystemParmData.aiAttrData[i].attrId);           // 属性ID
            Fill_LoraData_4B((uint32_t)SystemLoRaData.aiAttrSampleData[i].attrData);  // 属性值
            Fill_LoraData_4B(SystemParmData.aiAttrData[i].attrAlarmMinData);          // 属性下限值
            Fill_LoraData_4B(SystemParmData.aiAttrData[i].attrAlarmRecoverMinData);   // 属性恢复下限值
            Fill_LoraData_4B(SystemParmData.aiAttrData[i].attrAlarmMaxData);          // 属性上限值
            Fill_LoraData_4B(SystemParmData.aiAttrData[i].attrAlarmRecoverMaxData);   // 属性恢复上限值
            break;
        }
    }

#    endif

#    if defined(CONFIG_DTU_DIN)
    Fill_LoraData_1B((uint8_t)3);  // 数据长度
    for (uint8_t i = 0; i < SYSTEM_DIN_ATTRIBUTE_NUM; i++) {
        if (SystemParmData.dinAttrData[i].attrId == attrId) {
            Fill_LoraData_1B((uint8_t)SystemParmData.dinAttrData[i].attrId);  // 属性ID
            Fill_LoraData_1B(
                (uint8_t)(((SystemLoRaData.dinAttrSampleData[i].attrData & 0x000000FF) >> 0) & 0xFF));  // 属性值
            Fill_LoraData_1B(
                (uint8_t)(((SystemParmData.dinAttrData[i].attrData & 0x000000FF) >> 0) & 0xFF));  // 属性正常值
            break;
        }
    }
#    endif

    CRC16((void*)SystemLoRaData.appData, SystemLoRaData.appDataSize, &crc);

    Fill_LoraData_1B((crc >> 8) & 0xFF);
    Fill_LoraData_1B(crc & 0xFF);  // CRC检验值

    LOG_PRINTF(LL_DEBUG, "App_LoRa_Proto_SendAlarmData,attrId=%d:", attrId);
    for (uint8_t i = 0; i < SystemLoRaData.appDataSize; i++) {
        LOG_PRINTF(LL_DEBUG, "%02x ", SystemLoRaData.appData[i]);
    }
    LOG_PRINTF(LL_DEBUG, "\r\n");

    DeviceState = DEVICE_STATE_SEND;  // 开始发送数据
#endif
}
